package com.study.designmodes.service.strategy.component;

import com.study.designmodes.enums.BusinessCodeEnum;
import com.study.designmodes.service.strategy.ApiService;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 策略模式bean工厂
 * <p>
 * ApiFactory 获取接口实现bean,并存储到 ConcurrentHashMap，通过枚举获取对应的实现bean
 *
 * @author yyb8152
 * @since 20220402
 **/
@Component
public class ApiFactory implements InitializingBean {

    /**
     * 注入ApplicationContext对象
     */
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 初始化存储策的map
     */
    private static final Map<BusinessCodeEnum, ApiService> beans = new ConcurrentHashMap<>();

    /**
     * 从applicationContext 通过接口获取beans,并存储到 ConcurrentHashMap
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, ApiService> strategyMap = applicationContext.getBeansOfType(ApiService.class);
        if (MapUtils.isEmpty(strategyMap)) {
            return;
        }
        for (ApiService value : strategyMap.values()) {
            beans.put(value.supportedBusinessCodeEnum(), value);
        }

    }
/*    //方法二：不用实现初始化bean的InitializingBean接口，但需要添加注解@Bean("该方法名")
    @Bean("operations")
    public Map<BusinessCodeEnum, ApiService> operations(){
        Map<String, ApiService> strategyMap = applicationContext.getBeansOfType(ApiService.class);
        if(MapUtils.isEmpty(strategyMap)){
            return null;
        }
        for (ApiService value : strategyMap.values()) {
            beans.put(value.supportedBusinessCodeEnum(),value);
        }
        return beans;

    }*/

    public static ApiService getApiServiceByCode(BusinessCodeEnum businessCodeEnum) {
        return beans.get(businessCodeEnum);

    }
}
